package org.ragdollcat.secondaiagent.chatmemory;

import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.objenesis.strategy.StdInstantiatorStrategy;
import org.ragdollcat.secondaiagent.model.ContextMemoryRecord;
import org.ragdollcat.secondaiagent.service.ContextMemoryRecordService;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 基于数据库的对话记忆持久化
 */
@Slf4j
@Component
public class DbBasedChatMemory implements ChatMemory {

    @Resource
    private ContextMemoryRecordService contextMemoryRecordService;


    private static final Kryo kryo = new Kryo();

    static {
        kryo.setRegistrationRequired(false);
        // 设置实例化策略
        kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
    }


    @Override
    public void add(String conversationId, List<Message> messages) {
        log.info("conversationId:{},messages:{}", conversationId, messages);
        //根据conversationId从数据库中查询结果，并且反序列化
        List<Message> conversationMessages = getOrCreateConversation(conversationId);
        //将本次结果进行追加
        conversationMessages.addAll(messages);
        //重新存入数据库
        saveConversation(conversationId, conversationMessages);
    }



    @Override
    public List<Message> get(String conversationId, int lastN) {
        List<Message> allMessages = getOrCreateConversation(conversationId);
        return allMessages.stream()
                .skip(Math.max(0, allMessages.size() - lastN))
                .toList();
    }

    @Override
    public void clear(String conversationId) {
        ContextMemoryRecord contextMemoryRecord = getConversationDB(conversationId);
        if (ObjUtil.isNotEmpty(contextMemoryRecord)){
            contextMemoryRecordService.removeById(contextMemoryRecord.getId());
        }
    }


    private List<Message> getOrCreateConversation(String conversationId) {
        ContextMemoryRecord memoryRecord = getConversationDB(conversationId);
        List<Message> messages = new ArrayList<>();
        if (ObjUtil.isNotEmpty(memoryRecord) && memoryRecord.getMessage() != null) {
            // 从数据库记录中获取字节数组
            byte[] messageBytes = memoryRecord.getMessage();
            // 使用Kryo反序列化为List<Message>
            messages = deserializeMessages(messageBytes);
        }
        return messages;
    }

    /**
     * 根据Id查询上下文对象
     *
     * @param conversationId
     * @return
     */
    private ContextMemoryRecord getConversationDB(String conversationId) {
        return contextMemoryRecordService.getOne(new QueryWrapper<>(ContextMemoryRecord.class).eq("contextId", conversationId));
    }




    private void saveConversation(String conversationId, List<Message> conversationMessages) {
        ContextMemoryRecord conversationDB = getConversationDB(conversationId);
        //新增
        if (ObjUtil.isEmpty(conversationDB)){
            ContextMemoryRecord memoryRecord = new ContextMemoryRecord();
            memoryRecord.setContextId(conversationId);
            //将消息重新序列化
            memoryRecord.setMessage(serializeMessages(conversationMessages));
            contextMemoryRecordService.save(memoryRecord);
        }//更新
        else {
            ContextMemoryRecord memoryRecord = new ContextMemoryRecord();
            memoryRecord.setContextId(conversationId);
            //将消息重新序列化
            memoryRecord.setMessage(serializeMessages(conversationMessages));
            //根据contextId字段更新
            contextMemoryRecordService.update(memoryRecord,new QueryWrapper<>(ContextMemoryRecord.class).eq("contextId",conversationId));
        }
    }

    /**
     * 反序列化字节数组为List<Message>
     */
    private List<Message> deserializeMessages(byte[] data) {
        try (Input input = new Input(new ByteArrayInputStream(data))) {
            // 反序列化为List<Message>
            return kryo.readObject(input, ArrayList.class);
        } catch (Exception e) {
            // 处理反序列化异常，例如日志记录和返回空列表
            log.error("Failed to deserialize messages", e);
            return new ArrayList<>();
        }
    }

    // 对应的序列化方法（当你需要保存消息到数据库时使用）
    private byte[] serializeMessages(List<Message> messages) {
        if (messages == null || messages.isEmpty()) {
            return null;
        }

        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             Output output = new Output(baos)) {
            kryo.writeObject(output, messages);
            output.flush();
            return baos.toByteArray();
        } catch (Exception e) {
            log.error("Failed to serialize messages", e);
            return null;
        }
    }

}
